home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / pktdrvr.c < prev    next >
C/C++ Source or Header  |  1991-03-28  |  12KB  |  450 lines

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <dos.h>
  6. #include "global.h"
  7. #include "proc.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "enet.h"
  11. #include "arcnet.h"
  12. #include "ax25.h"
  13. #include "slip.h"
  14. #include "kiss.h"
  15. #include "iface.h"
  16. #include "ec.h"
  17. #include "arp.h"
  18. #include "trace.h"
  19. #include "pktdrvr.h"
  20. #include "config.h"
  21. #include "devparam.h"
  22.  
  23. static long access_type __ARGS((int intno,int if_class,int if_type,
  24.     int if_number, char *type,unsigned typelen,
  25.     INTERRUPT (*receiver) __ARGS((void)) ));
  26. static int driver_info __ARGS((int intno,int handle,int *version,
  27.     int *class,int *type,int *number,int *basic));
  28. static int release_type __ARGS((int intno,int handle));
  29. static int get_address __ARGS((int intno,int handle,char *buf,int len));
  30. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  31. static int pk_stop __ARGS((struct iface *iface));
  32. static int send_pkt __ARGS((int intno,char *buffer,unsigned length));
  33.  
  34.  
  35. static INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  36. static struct pktdrvr Pktdrvr[PK_MAX];
  37. static int Derr;
  38. static char Pkt_sig[] = "PKT DRVR";    /* Packet driver signature */
  39.  
  40. /*
  41.  * Send routine for packet driver
  42.  */
  43.  
  44. int
  45. pk_send(bp,iface,gateway,prec,del,tput,rel)
  46. struct mbuf *bp;    /* Buffer to send */
  47. struct iface *iface;    /* Pointer to interface control block */
  48. int32 gateway;        /* Ignored  */
  49. int prec;
  50. int del;
  51. int tput;
  52. int rel;
  53. {
  54.     if(iface == NULLIF){
  55.         free_p(bp);
  56.         return -1;
  57.     }
  58.     return (*iface->raw)(iface,bp);
  59. }
  60.  
  61. /* Send raw packet (caller provides header) */
  62. static int
  63. pk_raw(iface,bp)
  64. struct iface *iface;    /* Pointer to interface control block */
  65. struct mbuf *bp;    /* Data field */
  66. {
  67.     register struct pktdrvr *pp;
  68.     int16 size;
  69.     struct mbuf *bp1;
  70.  
  71.     pp = &Pktdrvr[iface->dev];
  72.     size = len_p(bp);
  73.  
  74.     dump(iface,IF_TRACE_OUT,pp->class,bp);
  75.     iface->rawsndcnt++;
  76.     iface->lastsent = secclock();
  77.  
  78.     /* Perform class-specific processing, if any */
  79.     switch(pp->class){
  80.     case CL_ETHERNET:
  81.         if(size < RUNT){
  82.             /* Pad the packet out to the minimum */
  83.             if((bp1 = alloc_mbuf(RUNT-size)) == NULLBUF){
  84.                 free_p(bp);
  85.                 return -1;
  86.             }
  87.             memset(bp1->data,0,RUNT-size);
  88.             bp1->cnt = RUNT-size;
  89.             append(&bp,bp1);
  90.             size = RUNT;
  91.         }
  92.         break;
  93.     case CL_KISS:
  94.         /* This *really* shouldn't be done here, but it was the
  95.          * easiest way. Put the type field for KISS TNC on front.
  96.          */
  97.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  98.             free_p(bp);
  99.             return -1;
  100.         }
  101.         bp = bp1;
  102.         bp->data[0] = PARAM_DATA;
  103.         size++;
  104.         break;
  105.     }
  106.     if(bp->next != NULLBUF){
  107.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  108.         bp1 = copy_p(bp,size);
  109.         free_p(bp);
  110.         bp = bp1;
  111.         if(bp == NULLBUF)
  112.             return -1;
  113.     }
  114.     send_pkt(pp->intno,bp->data,bp->cnt);
  115.     free_p(bp);
  116.     return 0;
  117. }
  118.  
  119. /* Packet driver receive routine. Called from an assembler hook that pushes
  120.  * the caller's registers on the stack so we can access and modify them.
  121.  * This is a rare example of call-by-location in C.
  122.  */
  123. INTERRUPT
  124. pkint(bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags, dev)
  125. unsigned short  bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags;
  126. int dev;
  127. {
  128.     register struct pktdrvr *pp;
  129.     struct phdr phdr;
  130.     
  131.     if(dev < 0 || dev >= PK_MAX)
  132.         return;    /* Unknown device */
  133.     pp = &Pktdrvr[dev];
  134.     if(pp->iface == NULLIF)
  135.         return;    /* Unknown device */
  136.     switch(ax){
  137.     case 0:    /* Space allocate call */
  138.         if((pp->buffer = alloc_mbuf(cx+sizeof(phdr))) != NULLBUF){
  139.             es = FP_SEG(pp->buffer->data);
  140.             di = FP_OFF(pp->buffer->data+sizeof(phdr));
  141.             pp->buffer->cnt = cx + sizeof(phdr);
  142.             phdr.iface = pp->iface;
  143.             phdr.type = pp->class;
  144.             memcpy(&pp->buffer->data[0],(char *)&phdr,sizeof(phdr));
  145.         } else {
  146.             es = di = 0;
  147.         }
  148.         break;
  149.     case 1:    /* Packet complete call */
  150.         enqueue(&Hopper,pp->buffer);
  151.         pp->buffer = NULLBUF;
  152.         break;
  153.     default:
  154.         break;
  155.     }
  156. }
  157.  
  158. /* Shut down the packet interface */
  159. static int
  160. pk_stop(iface)
  161. struct iface *iface;
  162. {
  163.     struct pktdrvr *pp;
  164.  
  165.     pp = &Pktdrvr[iface->dev];
  166.     /* Call driver's release_type() entry */
  167.     if(release_type(pp->intno,pp->handle1) == -1)
  168.         tprintf("%s: release_type error code %u\n",iface->name,Derr);
  169.  
  170.     if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  171.         release_type(pp->intno,pp->handle2);
  172.         release_type(pp->intno,pp->handle3);
  173.     }
  174.     pp->iface = NULLIF;
  175.     return 0;
  176. }
  177. /* Attach a packet driver to the system
  178.  * argv[0]: hardware type, must be "packet"
  179.  * argv[1]: software interrupt vector, e.g., x7e
  180.  * argv[2]: interface label, e.g., "trw0"
  181.  * argv[3]: maximum number of packets allowed on transmit queue, e.g., "5"
  182.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  183.  */
  184. int
  185. pk_attach(argc,argv,p)
  186. int argc;
  187. char *argv[];
  188. void *p;
  189. {
  190.     register struct iface *if_pk;
  191.     int class,type;
  192.     unsigned int intno;
  193.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  194.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  195.     static char revarptype[] = {REVARP_TYPE >> 8, REVARP_TYPE};
  196.     long handle;
  197.     int i;
  198. #ifdef    ARCNET
  199.     static char arcip[] = {ARC_IP};
  200.     static char arcarp[] = {ARC_ARP};
  201. #endif
  202.  
  203.     long drvvec;
  204.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  205.     register struct pktdrvr *pp;
  206.     char tmp[25];
  207.  
  208.     for(i=0;i<PK_MAX;i++){
  209.         if(Pktdrvr[i].iface == NULLIF)
  210.             break;
  211.     }
  212.     if(i >= PK_MAX){
  213.         tprintf("Too many packet drivers\n");
  214.         return -1;
  215.     }
  216.     if(if_lookup(argv[2]) != NULLIF){
  217.         tprintf("Interface %s already exists\n",argv[2]);
  218.         return -1;
  219.     }
  220.  
  221.     intno = htoi(argv[1]);
  222.     /* Verify that there's really a packet driver there, so we don't
  223.      * go off into the ozone (if there's any left)
  224.      */
  225.     drvvec = (long)getvect(intno);
  226.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  227.         FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig));
  228.     if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){
  229.         tprintf("No packet driver loaded at int 0x%x\n",intno);
  230.         return -1;
  231.     }
  232.     if_pk = (struct iface *)callocw(1,sizeof(struct iface));
  233.     if_pk->name = strdup(argv[2]);
  234.     if_pk->addr = Ip_addr;
  235.     pp = &Pktdrvr[i];
  236.     if_pk->mtu = atoi(argv[4]);
  237.     if_pk->dev = i;
  238.     if_pk->raw = pk_raw;
  239.     if_pk->stop = pk_stop;
  240.     pp->intno = intno;
  241.     pp->iface = if_pk;
  242.  
  243.      /* Version 1.08 of the packet driver spec dropped the handle
  244.       * requirement from the driver_info call.  However, if we are using
  245.       * a version 1.05 packet driver, the following call will fail.
  246.        */
  247.      if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  248.         /* Find out by exhaustive search what class this driver is (ugh) */
  249.         for(class=1;class<=NCLASS;class++){
  250.             /* Store handle in temp long so we can tell an
  251.              * error return (-1) from a handle of 0xffff
  252.              */
  253.             handle = access_type(intno,class,ANYTYPE,0,iptype,2,
  254.                 Pkvec[if_pk->dev]);
  255.             if(handle != -1 || Derr == TYPE_INUSE){
  256.                 pp->handle1 = handle;
  257.                 break;
  258.             }
  259.         }
  260.         /* Now that we know, release it and do it all over again with the
  261.          * right type fields
  262.          */
  263.         release_type(intno,pp->handle1);
  264.     }
  265.     switch(class){
  266.     case CL_ETHERNET:
  267.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  268.             Pkvec[if_pk->dev]);
  269.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  270.             Pkvec[if_pk->dev]);
  271.         pp->handle3 = access_type(intno,class,ANYTYPE,0,revarptype,2,
  272.             Pkvec[if_pk->dev]);
  273.         setencap(if_pk,"Ethernet");
  274.         /* Get hardware Ethernet address from driver */
  275.         if_pk->hwaddr = mallocw(EADDR_LEN);
  276.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  277.         if(if_pk->hwaddr[0] & 1){
  278.             tprintf("Warning! Interface '%s' has a multicast address:",
  279.              if_pk->name);
  280.             tprintf(" (%s)\n",
  281.              (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  282.         }
  283.         break;
  284. #ifdef    ARCNET
  285.     case CL_ARCNET:
  286.         pp->handle1 = access_type(intno,class,ANYTYPE,0,arcip,1,
  287.             Pkvec[if_pk->dev]);
  288.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arcarp,1,
  289.             Pkvec[if_pk->dev]);
  290.         if_pk->send = anet_send;
  291.         if_pk->output = anet_output;
  292.         /* Get hardware ARCnet address from driver */
  293.         if_pk->hwaddr = mallocw(AADDR_LEN);
  294.         get_address(intno,pp->handle1,if_pk->hwaddr,AADDR_LEN);
  295.         break;
  296. #endif
  297.     case CL_SERIAL_LINE:
  298.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  299.          Pkvec[if_pk->dev]);
  300.         setencap(if_pk,"SLIP");
  301.         break;
  302. #ifdef    AX25
  303.     case CL_KISS:    /* Note that the raw routine puts on the command */
  304.     case CL_AX25:
  305.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  306.          Pkvec[if_pk->dev]);
  307.         setencap(if_pk,"AX25");
  308.         if_pk->hwaddr = mallocw(AXALEN);
  309.         memcpy(if_pk->hwaddr,Mycall,AXALEN);
  310.         break;
  311. #endif
  312.     case CL_SLFP:
  313.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  314.          Pkvec[if_pk->dev]);
  315.         if_pk->send = pk_send;
  316.         setencap(if_pk,"SLFP");
  317.         get_address(intno,pp->handle1,(char *)&if_pk->addr,4);
  318.         break;
  319.     default:
  320.         tprintf("Packet driver has unsupported class %u\n",class);
  321.         free(if_pk->name);
  322.         free((char *)if_pk);
  323.         return -1;
  324.     }
  325.     pp->class = class;
  326.     if_pk->next = Ifaces;
  327.     Ifaces = if_pk;
  328.  
  329.     return 0;
  330. }
  331. static long
  332. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  333. int intno;
  334. int if_class;
  335. int if_type;
  336. int if_number;
  337. char *type;
  338. unsigned typelen;
  339. INTERRUPT (*receiver)();
  340. {
  341.     union REGS regs;
  342.     struct SREGS sregs;
  343.  
  344.     segread(&sregs);
  345.     regs.h.dl = if_number;        /* Number */
  346.     sregs.ds = FP_SEG(type);    /* Packet type template */
  347.     regs.x.si = FP_OFF(type);
  348.     regs.x.cx = typelen;        /* Length of type */
  349.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  350.     regs.x.di = FP_OFF(receiver);
  351.     regs.x.bx = if_type;        /* Type */
  352.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  353.     regs.h.al = if_class;        /* Class */
  354.     int86x(intno,®s,®s,&sregs);
  355.     if(regs.x.cflag){
  356.         Derr = regs.h.dh;
  357.         return -1;
  358.     } else
  359.         return regs.x.ax;
  360. }
  361. static int
  362. release_type(intno,handle)
  363. int intno;
  364. int handle;
  365. {
  366.     union REGS regs;
  367.  
  368.     regs.x.bx = handle;
  369.     regs.h.ah = RELEASE_TYPE;
  370.     int86(intno,®s,®s);
  371.     if(regs.x.cflag){
  372.         Derr = regs.h.dh;
  373.         return -1;
  374.     } else
  375.         return 0;
  376. }
  377. static int
  378. send_pkt(intno,buffer,length)
  379. int intno;
  380. char *buffer;
  381. unsigned length;
  382. {
  383.     union REGS regs;
  384.     struct SREGS sregs;
  385.  
  386.     segread(&sregs);
  387.     sregs.ds = FP_SEG(buffer);
  388.     sregs.es = FP_SEG(buffer); /* for buggy univation pkt driver - CDY */
  389.     regs.x.si = FP_OFF(buffer);
  390.     regs.x.cx = length;
  391.     regs.h.ah = SEND_PKT;
  392.     int86x(intno,®s,®s,&sregs);
  393.     if(regs.x.cflag){
  394.         Derr = regs.h.dh;
  395.         return -1;
  396.     } else
  397.         return 0;
  398. }
  399. static int
  400. driver_info(intno,handle,version,class,type,number,basic)
  401. int intno;
  402. int handle;
  403. int *version,*class,*type,*number,*basic;
  404. {
  405.     union REGS regs;
  406.  
  407.     regs.x.bx = handle;
  408.     regs.h.ah = DRIVER_INFO;
  409.     regs.h.al = 0xff;
  410.     int86(intno,®s,®s);
  411.     if(regs.x.cflag){
  412.         Derr = regs.h.dh;
  413.         return -1;
  414.     }
  415.     if(version != NULL)
  416.         *version = regs.x.bx;
  417.     if(class != NULL)
  418.         *class = regs.h.ch;
  419.     if(type != NULL)
  420.         *type = regs.x.dx;
  421.     if(number != NULL)
  422.         *number = regs.h.cl;
  423.     if(basic != NULL)
  424.         *basic = regs.h.al;
  425.     return 0;
  426. }
  427. static int
  428. get_address(intno,handle,buf,len)
  429. int intno;
  430. int handle;
  431. char *buf;
  432. int len;
  433. {
  434.     union REGS regs;
  435.     struct SREGS sregs;
  436.  
  437.     segread(&sregs);
  438.     sregs.es = FP_SEG(buf);
  439.     regs.x.di = FP_OFF(buf);
  440.     regs.x.cx = len;
  441.     regs.x.bx = handle;
  442.     regs.h.ah = GET_ADDRESS;
  443.     int86x(intno,®s,®s,&sregs);
  444.     if(regs.x.cflag){
  445.         Derr = regs.h.dh;
  446.         return -1;
  447.     }
  448.     return 0;
  449. }
  450.